package main

import (
	"context"
	relationserver "hertz_demo/kitex/relation/kitex_gen/relationserver"
	"hertz_demo/orm/db"

	"gorm.io/gorm"
)

// RelationServiceImpl implements the last service interface defined in the IDL.
type RelationServiceImpl struct{}

// FollowUser implements the RelationServiceImpl interface.
func (s *RelationServiceImpl) FollowUser(ctx context.Context, req *relationserver.FollowUserRequest) (resp *relationserver.FollowUserResponse, err error) {
	// TODO: Your code here...
	resp = new(relationserver.FollowUserResponse)
	relation := db.FollowRelation{
		UserId:       req.User.ID,
		FollowUserId: req.FollowerUserId,
	}
	err = db.DB.Transaction(func(tx *gorm.DB) error {
		var relationId int64 = 0
		tx.Raw("select `id` from `follow_relations` where `user_id`=? and `follow_user_id`=? and is_del=false for update",
			req.User.ID, req.FollowerUserId).Scan(&relationId)
		if relationId != 0 {
			return nil
		}
		if err := tx.Model(&db.FollowRelation{}).Create(&relation).Error; err != nil {
			return err
		}
		if err := tx.Model(&db.User{}).Where("id=?", req.FollowerUserId).Update("follower_count", gorm.Expr("follower_count + ?", 1)).Error; err != nil {
			return err
		}
		if err := tx.Model(&db.User{}).Where("id=?", req.User.ID).Update("follow_count", gorm.Expr("follow_count + ?", 1)).Error; err != nil {
			return err
		}
		return nil
	})
	// todo: sync redis
	return
}

// DisFollowUser implements the RelationServiceImpl interface.
func (s *RelationServiceImpl) DisFollowUser(ctx context.Context, req *relationserver.DisFollowUserRequest) (resp *relationserver.DisFollowUserResponse, err error) {
	// TODO: Your code here...
	resp = new(relationserver.DisFollowUserResponse)
	err = db.DB.Transaction(func(tx *gorm.DB) error {
		var relationId int64 = 0
		tx.Raw("select `id` from `follow_relations` where `user_id`=? and `follow_user_id`=? and is_del=false for update",
			req.User.ID, req.FollowerUserId).Scan(&relationId)
		if relationId == 0 {
			return nil
		}
		if err := tx.Model(&db.FollowRelation{}).Where("id=?", relationId).Update("is_del", true).Error; err != nil {
			return err
		}
		if err := tx.Model(&db.User{}).Where("id=?", req.FollowerUserId).Update("follower_count", gorm.Expr("follower_count - ?", 1)).Error; err != nil {
			return err
		}
		if err := tx.Model(&db.User{}).Where("id=?", req.User.ID).Update("follow_count", gorm.Expr("follow_count - ?", 1)).Error; err != nil {
			return err
		}
		return nil
	})
	// todo: sync redis
	return
}

// GetFollowList implements the RelationServiceImpl interface.
func (s *RelationServiceImpl) GetFollowList(ctx context.Context, req *relationserver.GetFollowListRequest) (resp *relationserver.GetFollowListResponse, err error) {
	// TODO: Your code here...
	resp = new(relationserver.GetFollowListResponse)
	// var resultList []models.User
	var followList []int64
	if err = db.DB.Model(&db.FollowRelation{}).Select("follow_user_id").Where("user_id=?", req.User.ID).Find(&followList).Error; err != nil {
		return
	}
	var dbUserList []db.User
	if err = db.DB.Model(&db.User{}).Find(&dbUserList, followList).Error; err != nil {
		return
	}
	for _, dbUser := range dbUserList {
		modelUser := relationserver.User{
			ID:            dbUser.ID,
			Name:          dbUser.Name,
			FollowCount:   dbUser.FollowCount,
			FollowerCount: dbUser.FollowerCount,
			IsFollow:      true,
		}
		resp.ResultList = append(resp.ResultList, &modelUser)
	}
	return
}
